/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package guzik.lukasz.snpmanager.servlets;

import SnpDbEntities.Category;
import SnpDbEntities.Snippet;
import SnpDbEntities.User;
import SnpDbHndInterfaces.DBCatHandling;
import SnpDbHndInterfaces.DBConnectable;
import SnpDbHndInterfaces.DBSnpHandling;
import SnpDbHndInterfaces.DBUsrHandling;
import java.io.IOException;
import java.io.PrintWriter;
import java.rmi.RemoteException;
import java.util.LinkedHashMap;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;

/**
 *
 * @author byku
 */
@WebServlet(name = "MainServlet", urlPatterns =
{
    "/MainServlet"
})
public class MainServlet extends HttpServlet
{
    private HttpSession httpSession = null;

    /** 
     * Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
	    throws ServletException, IOException
    {
	httpSession = request.getSession();
	String dbSession;
	User connectedUser = (User) httpSession.getAttribute("connected_user");

	response.setContentType("text/html;charset=UTF-8");
	PrintWriter out = response.getWriter();
	try
	{
	    dbSession = (String) httpSession.getAttribute("db_session");
	    if(dbSession == null)
	    {
		getServletContext().getRequestDispatcher("/login.jsp").forward(request, response);
	    } else
	    {
		out.println("<html>");
		out.println("<head>");
		out.println("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">");
		out.println("<title>Snippet Manager Web Client</title>");
		out.println("</head>");
		out.println("<body>");
		if(connectedUser != null)
		{
		    out.print(connectedUser);
		}
		out.println(" <a href=\"LoginServlet?disconnect=true\">Logout</a><bt><br>");

		out.println("<table align=\"left\">");
		out.println("<tr valign=\"top\">");

		out.println("<td>");
		out.println("<table>");
		out.println("<tr>");
		out.println("<td>");
		out.println("<a href=\"index.jsp\">Prywatne</a>");
		out.println("</td>");
		out.println("<td>");
		out.println("<a href=\"index.jsp?pubcat=true\">Publiczne</a>");
		out.println("</td>");
		out.println("</tr>");
		out.println("<tr>");
		out.println("<td colspan=\"2\">");
		insertSnippetTree(out, "true".equals(request.getParameter("pubcat")));
		out.println("</td>");
		out.println("</tr>");
		out.println("</table>");
		out.println("</td>");

		out.println("<td>");
		if(request.getParameter("snpid") != null)
		{
		    snippetToHtml(out, Integer.parseInt(request.getParameter("snpid")), "true".equals(request.getParameter("pubsnp")));
		}
		out.println("</td>");

		out.println("</tr>");
		out.println("</table>");

		out.println("</body>");
		out.println("</html>");
	    }
	} catch(RemoteException e)
	{
	    e.printStackTrace(out);
	} finally
	{
	    out.close();
	}
    }

    // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
    /** 
     * Handles the HTTP <code>GET</code> method.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
	    throws ServletException, IOException
    {
	processRequest(request, response);
    }

    /** 
     * Handles the HTTP <code>POST</code> method.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
	    throws ServletException, IOException
    {
	processRequest(request, response);
    }

    /** 
     * Returns a short description of the servlet.
     * @return a String containing servlet description
     */
    @Override
    public String getServletInfo()
    {
	return "Short description";
    }// </editor-fold>

    private void insertSnippetTree(PrintWriter out, boolean isPublic) throws
	    RemoteException
    {
	String dbSession = (String) httpSession.getAttribute("db_session");
	DBCatHandling catHandler = ((DBConnectable) getServletContext().getAttribute("snpmgr_db_connection")).getCatHandler(dbSession);
	DBSnpHandling snpHandler = ((DBConnectable) getServletContext().getAttribute("snpmgr_db_connection")).getSnpHandler(dbSession);
	LinkedHashMap<Integer, Category> allCategories;
	LinkedHashMap<Integer, Snippet> allSnippets;

	allCategories = isPublic ? catHandler.getAllPublicCategories() : catHandler.getAllPrivateCategories();
	allSnippets = isPublic ? snpHandler.getAllPublicSnippets() : snpHandler.getAllPrivateSnippets();

	DefaultTreeModel treeModel = new ExtendedTreeModel(new DefaultMutableTreeNode("ROOT"));
	addRootItemsToTree(treeModel, allCategories, allSnippets, false);

	DefaultMutableTreeNode child = (DefaultMutableTreeNode) ((DefaultMutableTreeNode) treeModel.getRoot()).getFirstChild();

	out.println("<ul>");
	do
	{
	    out.print("<li>");
	    out.println((Category) child.getUserObject());
	    subNodesToHtml(child, out, isPublic);
	    child = child.getNextSibling();
	    out.println("</li>");
	} while(child != null);
	out.println("</ul>");
    }

    private void addRootItemsToTree(DefaultTreeModel model,
	    LinkedHashMap<Integer, Category> categories,
	    LinkedHashMap<Integer, Snippet> snippets,
	    boolean addEmpty)
    {

	DefaultMutableTreeNode root = new DefaultMutableTreeNode("ROOT");
	boolean isntEmpty = false;

	for(Category cat : categories.values())
	{
	    if(cat.getParentId() == 0)
	    {
		DefaultMutableTreeNode catNode = new DefaultMutableTreeNode(cat);
		isntEmpty = addSubItemsToTree(categories, snippets, cat.getId(), model, catNode, addEmpty);

		if(isntEmpty || addEmpty)
		{
		    model.insertNodeInto(catNode, root, 0);
		}
	    }
	}

	model.setRoot(root);
    }

    private boolean addSubItemsToTree(LinkedHashMap<Integer, Category> categories,
	    LinkedHashMap<Integer, Snippet> snippets, Integer actualCat,
	    DefaultTreeModel model, DefaultMutableTreeNode node,
	    boolean addEmpty)
    {
	boolean isntEmpty = false;

	for(Snippet snp : snippets.values())
	{
	    if(snp.getCategoryId() == categories.get(actualCat).getId())
	    {
		model.insertNodeInto(new DefaultMutableTreeNode(snp), node, 0);
		isntEmpty = true;
	    }
	}

	for(Category cat : categories.values())
	{
	    if(cat.getParentId() == categories.get(actualCat).getId())
	    {
		DefaultMutableTreeNode subNode = new DefaultMutableTreeNode(cat);
		if(addSubItemsToTree(categories, snippets, cat.getId(), model, subNode, addEmpty)
			|| addEmpty)
		{
		    isntEmpty = true;
		    model.insertNodeInto(subNode, node, 0);
		}
	    }
	}

	return isntEmpty;
    }

    private void subNodesToHtml(DefaultMutableTreeNode node, PrintWriter out, boolean isPublic)
    {
	int childCount = node.getChildCount();
	if(childCount > 0)
	{
	    DefaultMutableTreeNode child = (DefaultMutableTreeNode) node.getFirstChild();

	    out.println("<ul>");
	    do
	    {
		out.println("<li>");
		if(child.getUserObject() instanceof Category)
		{
		    out.println(((Category) child.getUserObject()));
		    subNodesToHtml(child, out, isPublic);
		} else if(child.getUserObject() instanceof Snippet)
		{
		    out.print("<a href=\"index.jsp?");
		    if(isPublic)
		    {
			out.print("pubcat=true&pubsnp=true&");
		    }
		    out.print("snpid=" + ((Snippet) child.getUserObject()).getId());
		    out.print("\">" + (Snippet) child.getUserObject() + "</a>");
		}
		out.println("</li>");

		child = (DefaultMutableTreeNode) node.getChildAfter(child);
	    } while(child != null);
	    out.println("</ul>");
	}
    }

    private void snippetToHtml(PrintWriter out, int snpId, boolean isPublic)
	    throws RemoteException
    {
	String dbSession = (String) httpSession.getAttribute("db_session");
	DBSnpHandling snpHandler = ((DBConnectable) getServletContext().getAttribute("snpmgr_db_connection")).getSnpHandler(dbSession);
	DBUsrHandling usrHandler = ((DBConnectable) getServletContext().getAttribute("snpmgr_db_connection")).getUserHandler(dbSession);
	Snippet snp;
	User owner;

	snp = isPublic ? snpHandler.getPublicSnippet(snpId, true) : snpHandler.getPrivateSnippet(snpId, true);
	owner = usrHandler.getUser(snp.getOwnerId());

	out.println("<table align=\"left\" border>");

	out.println("<tr>");
	out.println("<td>");
	out.println("Nazwa:");
	out.println("</td>");
	out.println("<td>");
	out.println(snp);
	out.println("</td>");
	out.println("</tr>");

	out.println("<tr>");
	out.println("<td>");
	out.println("Autor");
	out.println("</td>");
	out.println("<td>");
	out.println(owner);
	out.println("</td>");
	out.println("</tr>");

	out.println("<tr>");
	out.println("<td>");
	out.println("Opis:");
	out.println("</td>");
	out.println("<td><pre>");
	if(snp.getDesc() != null)
	{
	    out.println(snp.getDesc());
	}
	out.println("</pre></td>");
	out.println("</tr>");

	out.println("<tr>");
	out.println("<td>");
	out.println("Ostatnia modyfikacja");
	out.println("</td>");
	out.println("<td>");
	out.println(snp.getLastModified());
	out.println("</td>");
	out.println("</tr>");

	out.println("<tr><td colspan=\"2\"><code><pre>");
	out.println(snp.getData());
	out.println("</pre></code></tr></td>");
	
	out.println("</table>");
    }
}
